//
// Created by jintian on 17-12-18.
//

#include "face_detector.h"

/**
 * construct of face detector
 */
FaceDetector::FaceDetector() {
    cout << "Let me see what is the instance landmarks: " << landmarks_f << endl;
    if (!landmarks_f.empty()) {
        // load shape detector
        this->detector = dlib::get_frontal_face_detector();
        dlib::deserialize(landmarks_f) >> this->sp;
        cout << "Load landmarks succeed, and this will only do once!\n";
    } else {
        cout << "Error! You must set_shape_detector_landmarks before detect!\n";
        exit(0);
    }
}

/**
 * this method do the detect things
 * @param image_f
 */
void FaceDetector::detect_on_image_file(const string image_f) {
    cout << "--  detect from: " << image_f << endl;
    // get image and detect it
    dlib::array2d<dlib::rgb_pixel> image;
    dlib::load_image(image, image_f);
    dlib::pyramid_up(image);

    long long detectTime = cv::getTickCount();
    vector<dlib::rectangle> detections = instance->detector(image, 1);
    detectTime = cv::getTickCount() - detectTime;
    cout << "   detect time : " << detectTime / cv::getTickFrequency() << " s" << endl;
    cout << "   Number of faces detected: " << detections.size() << endl;

    std::vector<dlib::full_object_detection> shapes;


    //int64 t;
    long long total = cv::getTickCount();
    for (unsigned long j = 0; j < detections.size(); ++j)
    {
        long long t = cv::getTickCount();
        dlib::full_object_detection shape = sp(image, detections[j]);
        cout << "   number of parts: " << shape.num_parts() << endl;
        cout << "   pixel position of first part:  " << shape.part(0) << endl;
        cout << "   pixel position of second part: " << shape.part(1) << endl;
        cout << endl;
        // You get the idea, you can get all the face part locations if
        // you want them.  Here we just store them in shapes so we can
        // put them on the screen.
        shapes.push_back(shape);

        t = cv::getTickCount() - t;
        cout << "   process time : " << t / cv::getTickFrequency() << " s" << endl;
    }
    total = cv::getTickCount() - total;
    cout << "process time : " << total / cv::getTickFrequency() << " s" << endl;

    // Now let's view our face poses on the screen.
    win.clear_overlay();
    win.set_image(image);
    win.add_overlay(render_face_detections(shapes));
    win.show();

    // We can also extract copies of each face that are cropped, rotated upright,
    // and scaled to a standard size as shown here:
    dlib::array<dlib::array2d<dlib::rgb_pixel> > face_chips;
    extract_image_chips(image, get_face_chip_details(shapes), face_chips);
    win_faces.set_image(tile_images(face_chips));
    win_faces.show();
}

FaceDetector::FaceDetector(const FaceDetector &) {
    // in here we load the detector

}

// init instance outside class
FaceDetector* FaceDetector::instance = nullptr;
FaceDetector* FaceDetector::getInstance() {
    if (instance == nullptr) {
        instance = new FaceDetector();
    }
    return instance;
}


void FaceDetector::set_shape_detector_landmarks(const string landmarks_f) {
    instance->landmarks_f = landmarks_f;
}